package com.ruoyi.ring.service.impl;

import cn.hutool.core.convert.Convert;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.ApprovalStateEnums;
import com.ruoyi.common.enums.JoinTypeEnums;
import com.ruoyi.common.enums.MemberTypeEnums;
import com.ruoyi.common.enums.TimeUnitEnums;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.Builder;
import com.ruoyi.ring.config.GroupCodeGenerator;
import com.ruoyi.ring.domain.RingGroup;
import com.ruoyi.ring.domain.RingGroupMember;
import com.ruoyi.ring.domain.RingGroupMessage;
import com.ruoyi.ring.domain.dto.*;
import com.ruoyi.ring.domain.vo.*;
import com.ruoyi.ring.mapper.RingGroupMapper;
import com.ruoyi.ring.mapper.RingGroupMemberMapper;
import com.ruoyi.ring.mapper.RingGroupMessageMapper;
import com.ruoyi.ring.service.IAppGroupService;
import com.ruoyi.ring.service.IFoodInfoSecondService;
import com.ruoyi.ring.service.IRingPhysicalConditionService;
import com.ruoyi.ring.service.IRingSleepDetailService;
import com.ruoyi.system.mapper.SysUserMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class AppGroupServiceImpl implements IAppGroupService {

    @Resource
    private IRingPhysicalConditionService ringPhysicalConditionService;

    @Resource
    private IRingSleepDetailService ringSleepDetailService;
    @Resource
    private IFoodInfoSecondService foodInfoService;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private RingGroupMapper ringGroupMapper;

    @Resource
    private RingGroupMemberMapper ringGroupMemberMapper;

    @Resource
    private RingGroupMessageMapper ringGroupMessageMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int addGroup(RingGroupDTO dto) {
        try {
            String groupCode = dto.getGroupCode();
            Date date = new Date();
            long userId = SecurityUtils.getUserId();
            SysUser sysUser = sysUserMapper.queryUserHealthQuestion(userId);
            RingGroup ringGroup = Convert.convert(RingGroup.class,dto);
            ringGroup.setUserId(userId);
            ringGroup.setGroupCreator(sysUser.getNickName());
            ringGroup.setGroupCode(groupCode != null ?groupCode : queryCode());
            ringGroup.setGroupSortTime(date);
            ringGroup.setCreateTime(date);
            ringGroupMapper.insertRingGroup(ringGroup);

            RingGroupMember groupMember = new RingGroupMember();
            groupMember.setGroupId(ringGroup.getId());
            groupMember.setUserId(userId);
            groupMember.setMemberAccount(sysUser.getUserName());
            groupMember.setMemberName(sysUser.getNickName());
            groupMember.setMemberAvatar(sysUser.getAvatar());
            groupMember.setJoinTime(date);
            groupMember.setMemberType(MemberTypeEnums.GROUP_OWNER.getCode());
            groupMember.setCreateTime(date);
            return ringGroupMemberMapper.insertRingGroupMember(groupMember);
        }catch (Exception e){
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public List<RingGroupResultVO> queryGroupList() {
        GroupQueryDTO queryDTO = new GroupQueryDTO();
        queryDTO.setUserId(SecurityUtils.getUserId());
        return ringGroupMapper.queryGroupList(queryDTO);
    }

    @Override
    public RingGroupResultVO queryGroup(Long id) {
        return ringGroupMapper.queryGroup(id);
    }

    @Override
    public int editGroupSort(Long id) {
        RingGroup ringGroup = new RingGroup();
        ringGroup.setId(id);
        ringGroup.setGroupSortTime(new Date());
        return ringGroupMapper.updateRingGroup(ringGroup);
    }

//    @Override
//    public int addGroupMember(ApplyGroupDTO applyGroupDTO) {
//
//        return 0;
//    }

    @Override
    public int applyJoinGroup(ApplyGroupDTO applyGroupDTO) {
        //邀请加入：1，申请加入：2
        String groupCode = applyGroupDTO.getGroupCode();
        RingGroup ringGroup = ringGroupMapper.selectOneRingGroup(Builder.of(RingGroup::new).with(RingGroup::setGroupCode, groupCode).build());
        if(ringGroup != null){
            SysUser sysUser = sysUserMapper.queryGroupByUserName(applyGroupDTO.getApplyInfo());
            long applicantId = sysUser.getUserId();
            String nickName = sysUser.getNickName();//申请人/邀请人姓名
            String groupName = ringGroup.getGroupName();//组名
            long groupCreatorId = ringGroup.getUserId();
            String groupCreator = ringGroup.getGroupCreator();//群组创建人
            String joinType = applyGroupDTO.getJoinType();
            String remark = "";
            String remark1 = "已加入该群组";
            String remark2 = "";
            if(JoinTypeEnums.INVITATION.getCode().equals(joinType)){
                remark  = groupCreator+"邀请您加入"+groupName+"群组！";
                remark2 = "该群组已邀请，请勿重复邀请！";
            }
            if(JoinTypeEnums.APPLY.getCode().equals(joinType)){
                remark  = nickName+"申请加入"+groupName+"群组！";
                remark2 = "该群组已申请，请勿重复申请！";
            }
            RingGroupMessage ringGroupMessage = ringGroupMessageMapper.selectOneRingGroupMessage(Builder.of(RingGroupMessage::new).
                    with(RingGroupMessage::setGroupCode,groupCode).
                    with(RingGroupMessage::setApplicantId,applicantId).
                    with(RingGroupMessage::setGroupCreatorId,groupCreatorId).build());
            if(ringGroupMessage != null){
                if(ApprovalStateEnums.APPROVED.getCode().equals(ringGroupMessage.getApprovalState())){
                    throw new RuntimeException(remark1);
                }else if(ApprovalStateEnums.PENDING.getCode().equals(ringGroupMessage.getApprovalState())){
                    throw new RuntimeException(remark2);
                }
            }
            RingGroupMessage groupMessage = new RingGroupMessage();
            groupMessage.setApplicantId(applicantId);
            groupMessage.setApplicantName(nickName);
            groupMessage.setGroupName(groupName);
            groupMessage.setGroupCreatorId(groupCreatorId);
            groupMessage.setGroupCreator(groupCreator);
            groupMessage.setGroupCode(groupCode);
            groupMessage.setApplicantTime(new Date());
            groupMessage.setJoinType(joinType);
            groupMessage.setRemark(remark);
            groupMessage.setCreateTime(new Date());
            return ringGroupMessageMapper.insertRingGroupMessage(groupMessage);
        }else {
            throw new RuntimeException("群组码不正确，请重新输入！");
        }
    }

    @Override
    public String queryGroupCodeById(Long id) {
        RingGroup ringGroup = ringGroupMapper.selectRingGroupById(id);
        return ringGroup != null ? ringGroup.getGroupCode() : null;
    }

    @Override
    public String queryGroupCode() {
        return queryCode();
    }

    @Override
    public List<RingGroupMessageResultVO> queryInviterMessageList(RingGroupMessage ringGroupMessage) {
        ringGroupMessage.setGroupCreatorId(SecurityUtils.getUserId());
//        ringGroupMessage.setJoinType(JoinTypeEnums.INVITATION.getCode());
        List<RingGroupMessage> groupMessageList = ringGroupMessageMapper.queryMessageList(ringGroupMessage);
        List<RingGroupMessageResultVO> resultVOList = Convert.toList(RingGroupMessageResultVO.class,groupMessageList);
        return resultVOList;
    }

    @Override
    public List<RingGroupMessageResultVO> queryApplyMessageList(RingGroupMessage ringGroupMessage) {
        ringGroupMessage.setApplicantId(SecurityUtils.getUserId());
//        ringGroupMessage.setJoinType(JoinTypeEnums.APPLY.getCode());
        List<RingGroupMessage> groupMessageList = ringGroupMessageMapper.queryMessageList(ringGroupMessage);
        List<RingGroupMessageResultVO> resultVOList = Convert.toList(RingGroupMessageResultVO.class,groupMessageList);
        return resultVOList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int approval(ApprovalDTO dto) {
        try {
            long userId = dto.getApplicantId();
            Date date = new Date();
            RingGroupMessage ringGroupMessage = ringGroupMessageMapper.selectRingGroupMessageById(dto.getId());
            ringGroupMessage.setApprovalState(dto.getApprovalState());
            ringGroupMessageMapper.updateRingGroupMessage(ringGroupMessage);

            SysUser sysUser = sysUserMapper.queryUserHealthQuestion(userId);
            RingGroup ringGroup = ringGroupMapper.selectOneRingGroup(Builder.of(RingGroup::new).with(RingGroup::setGroupCode, dto.getGroupCode()).build());
            RingGroupMember groupMember = new RingGroupMember();
            groupMember.setGroupId(ringGroup.getId());
            groupMember.setUserId(userId);
            groupMember.setMemberAccount(sysUser.getUserName());
            groupMember.setMemberName(sysUser.getNickName());
            groupMember.setMemberAvatar(sysUser.getAvatar());
            groupMember.setJoinTime(date);
            groupMember.setMemberType(MemberTypeEnums.GROUP_MEMBER.getCode());
            groupMember.setRemark(dto.getRemark());
            groupMember.setCreateTime(date);
            return ringGroupMemberMapper.insertRingGroupMember(groupMember);
        }catch (Exception e){
            throw new RuntimeException(e.getMessage());
        }

    }

    @Override
    public int editGroupMemberRemark(MemberRemarkDTO dto) {
        RingGroupMember groupMember = new RingGroupMember();
        groupMember.setId(dto.getId());
        groupMember.setMemberName(dto.getMemberName());
        return ringGroupMemberMapper.updateRingGroupMember(groupMember);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int removeGroup(Long id) {
        try {
            ringGroupMemberMapper.deleteRingGroupMemberByCondition(Builder.of(RingGroupMember::new).with(RingGroupMember::setGroupId,id).build());
            return ringGroupMapper.deleteRingGroupById(id);
        }catch (Exception e){
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public int removeGroupMember(Long id) {
        return ringGroupMemberMapper.deleteRingGroupMemberById(id);
    }

    @Override
    public List<RingGroupMemberResultVO> queryGroupMemberList(Long id) {
        List<RingGroupMember> groupMemberList = ringGroupMemberMapper.selectRingGroupMemberList(Builder.of(RingGroupMember::new).with(RingGroupMember::setGroupId,id).build());
        List<RingGroupMemberResultVO> resultVOList = Convert.toList(RingGroupMemberResultVO.class,groupMemberList);
        return resultVOList;
    }

    @Override
    public List<GroupResultVO> queryPhysicalVitality(Long groupId) {
        List<GroupMemberResultVO> resultVOList = ringGroupMemberMapper.queryGroupMember(groupId);
        List<GroupResultVO> groupResultVOS = new ArrayList<>();
        resultVOList.forEach(reslut ->{
            long userId = reslut.getUserId();
            GroupResultVO groupResultVO = new GroupResultVO();
            PhysicalConditionDTO physicalConditionDTO = new PhysicalConditionDTO();
            physicalConditionDTO.setDailyValue(DateUtils.dateTime(DateUtils.YYYY_MM_DD,DateUtils.getDate()));
            physicalConditionDTO.setDeviceSn(reslut.getDeviceSn());
            physicalConditionDTO.setUserId(userId);
            ConditionScoreVO conditionScoreVO = ringPhysicalConditionService.queryConditionScore(physicalConditionDTO);
            groupResultVO.setUserId(userId);
            groupResultVO.setUserName(userId == SecurityUtils.getUserId() ? "自己" : reslut.getMemberName());
            groupResultVO.setValue(conditionScoreVO != null && conditionScoreVO.getTotalScore() != null ? conditionScoreVO.getTotalScore() : 0);
            groupResultVOS.add(groupResultVO);
        });
        return groupResultVOS;
    }

    @Override
    public List<GroupResultVO> querySleep(Long groupId) {
        List<GroupMemberResultVO> resultVOList = ringGroupMemberMapper.queryGroupMember(groupId);
        List<GroupResultVO> groupResultVOS = new ArrayList<>();
        resultVOList.forEach(reslut ->{
            long userId = reslut.getUserId();
            GroupResultVO groupResultVO = new GroupResultVO();
            RingSleepDetailInfoDTO sleepDetailInfoDTO = new RingSleepDetailInfoDTO();
            sleepDetailInfoDTO.setDailyValue(DateUtils.dateTime(DateUtils.YYYY_MM_DD,DateUtils.getDate()));
            sleepDetailInfoDTO.setDeviceSn(reslut.getDeviceSn());
            sleepDetailInfoDTO.setType(TimeUnitEnums.DAY.getCode());
            RingSleepQualityScoreVO qualityScoreVO = ringSleepDetailService.queryQualityScore(sleepDetailInfoDTO);
            groupResultVO.setUserId(userId);
            groupResultVO.setUserName(userId == SecurityUtils.getUserId() ? "自己" : reslut.getMemberName());
            int score = qualityScoreVO != null && qualityScoreVO.getSleepScore() != null ? qualityScoreVO.getSleepScore() : 0;
            if(score < 70) groupResultVO.setIsQualify("0");;
            if(score > 69) groupResultVO.setIsQualify("1");;
            groupResultVO.setValue(score);
            groupResultVOS.add(groupResultVO);
        });
        int maxScore = groupResultVOS.stream()
                .mapToInt(GroupResultVO::getValue)
                .max()
                .orElse(0); // 若没有成员，默认最大值为0

        groupResultVOS.forEach(vo -> {
            // 今日最佳  最佳：1  其他：0
            vo.setOptimum((maxScore > 0 && vo.getValue() == maxScore) ? "1" : "0");
        });
        return groupResultVOS;
    }

    @Override
    public List<GroupResultVO> queryEnergyBalance(Long groupId) {
        List<GroupMemberResultVO> resultVOList = ringGroupMemberMapper.queryGroupMember(groupId);
        List<GroupResultVO> groupResultVOS = new ArrayList<>();
        resultVOList.forEach(reslut ->{
            long userId = reslut.getUserId();
            GroupResultVO groupResultVO = new GroupResultVO();
            GeneralSecondDTO secondDTO = new GeneralSecondDTO();
            secondDTO.setRecordDate(DateUtils.dateTime(DateUtils.YYYY_MM_DD,DateUtils.getDate()));
            secondDTO.setDeviceSn(reslut.getDeviceSn());
            secondDTO.setUserId(userId);
            secondDTO.setType(TimeUnitEnums.DAY.getCode());
            EnergyBalanceVO energyBalanceVO = foodInfoService.queryEnergyBalance(secondDTO);
            groupResultVO.setUserId(userId);
            groupResultVO.setUserName(userId == SecurityUtils.getUserId() ? "自己" : reslut.getMemberName());
            groupResultVO.setValue(energyBalanceVO != null && energyBalanceVO.getEnergyBalance() != null ? energyBalanceVO.getEnergyBalance() : 0);
            groupResultVOS.add(groupResultVO);
        });
        return groupResultVOS;
    }

    /**
     * 获取群组码
     */
    public String queryCode(){
        List<String> usedCodes = ringGroupMapper.queryUsedCodes();
        return GroupCodeGenerator.generateUniqueGroupCode(usedCodes);
    }
}
